package edu.nf.redismqes.service;

import edu.nf.redismqes.common.config.RabbitConfig;
import edu.nf.redismqes.common.confirm.RabbitManager;
import edu.nf.redismqes.mappers.newsMapper;
import edu.nf.redismqes.model.docmentt.NewDoc;
import edu.nf.redismqes.model.entity.New;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.client.elc.NativeQuery;
import org.springframework.data.elasticsearch.client.elc.NativeQueryBuilder;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.HighlightQuery;
import org.springframework.data.elasticsearch.core.query.highlight.Highlight;
import org.springframework.data.elasticsearch.core.query.highlight.HighlightField;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.amqp.core.Message;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * @ Author bin
 * @ Create  2025/10/21 下午7:01
 **/
@Service
@Slf4j
public class NewProduceService {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private newsMapper newsMapper;

    @Autowired
    private ElasticsearchOperations operations;

    /**
     * 添加新闻
     * */
    public void addNews(New news) {
        send("addNews", news);
    }

    /**
     * 修改新闻
     * */
    public void updateNews(New news) {
        send("updateNews", news);
    }

    /**
     * 删除新闻
     * */
    public void delNews(Integer newsId) {
        New news = new New();
        news.setId(newsId);
        send("delNews", news);
    }

    /**
     * 通过id查询缓存里的新闻详情
     * */
    public New getNewsById(Integer newsId) {
        //在缓存里查询
        New news = (New)redisTemplate.opsForValue().get("news:" + newsId);
        if (news == null){
            New aNew = newsMapper.selectById(newsId);
            redisTemplate.opsForValue().set("news:" + newsId, aNew);
            news = aNew;
        }
        return news;
    }

    /**
     * 通过es分页查询新闻
     * */
    public List<New> list(Integer pageNum, Integer pageSize) {
        List<New> news = new ArrayList<>();
        NativeQuery query = NativeQuery.builder()
                .withPageable(PageRequest.of(pageNum, pageSize))
                .build();

        SearchHits<NewDoc> search = operations.search(query, NewDoc.class);

        search.getSearchHits().forEach(hit -> {
            New newNews = new New();
            BeanUtils.copyProperties(hit.getContent(), newNews);
            news.add(newNews);
        });
        return news;
    }

    /**
     * 高亮+bool查询：用于搜索查询
     * */
    public List<New> search(String keyword) {
        List<New> news = new ArrayList<>();
        NativeQueryBuilder queryBuilder = NativeQuery.builder();
        //构建多个高亮字段
        HighlightField title = new HighlightField("title");
        HighlightField content = new HighlightField("content");
        HighlightField author = new HighlightField("author");
        HighlightField type = new HighlightField("type");
        //封装成高亮对象
        Highlight highlight = new Highlight(List.of(title, content, author, type));
        //执行高亮查询
        queryBuilder.withQuery( q -> q.bool(
                b -> b
                        .should(s -> s.match(m -> m.field("title").query(keyword)))
                        .should(s -> s.match(m -> m.field("content").query(keyword)))
                        .should(s -> s.match(m -> m.field("author").query(keyword)))
                        .should(s -> s.match(m -> m.field("type").query(keyword)))
                 )
        ).withHighlightQuery(new HighlightQuery( highlight,NewDoc.class));
        //返回查询结果
        SearchHits<NewDoc> search = operations.search(queryBuilder.build(), NewDoc.class);
        search.getSearchHits().forEach(hit -> {
            New newNews = new New();
            NewDoc doc = hit.getContent();
            newNews.setId(doc.getId());
            newNews.setTitle(getHighlightOrDefault(hit, "title"));
            newNews.setContent(getHighlightOrDefault(hit, "content"));
            newNews.setAuthor(getHighlightOrDefault(hit, "author"));
            newNews.setType(getHighlightOrDefault(hit, "type"));
            news.add(newNews);
        });

        return news;
    }



    private String getHighlightOrDefault(SearchHit<NewDoc> hit, String field) {
        var highlights = hit.getHighlightField(field);
        if (!highlights.isEmpty()) {
            return highlights.getFirst();
        }
        // 否则返回原字段内容
        return switch (field) {
            case "title" -> hit.getContent().getTitle();
            case "content" -> hit.getContent().getContent();
            case "author" -> hit.getContent().getAuthor();
            case "type" -> hit.getContent().getType();
            default -> "";
        };
    }


    public void send(String action, New news) {
        MessageProperties props = new MessageProperties();
        props.setHeader("action", action);
        props.setContentType("application/json");

        try {
            String json = new ObjectMapper().writeValueAsString(news);
            Message message = new Message(json.getBytes(StandardCharsets.UTF_8), props);
            rabbitTemplate.send(RabbitConfig.EXCHANGE_NAME, RabbitConfig.ROUTING_KEY, message);
        } catch (Exception e) {
            throw new RuntimeException("发送消息失败", e);
        }
    }
}
